package cn.wdm.ymcc.service.impl;

import cn.wdm.ymcc.CourseDoc;
import cn.wdm.ymcc.dto.SearchCourseDto;
import cn.wdm.ymcc.dto.AggrsBucket;
import cn.wdm.ymcc.dto.EsAggsPageList;
import cn.wdm.ymcc.esmapper.HighlightResultMapper;
import cn.wdm.ymcc.repository.EsCourseRepository;
import cn.wdm.ymcc.result.PageList;
import cn.wdm.ymcc.service.IEscourseService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class EscourseServiceImpl implements IEscourseService {
    //此类专门操作Es的CRUD
    @Autowired
    private EsCourseRepository esCourseRepository;
    //es高亮的mapper
    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Override
    public void savaCourse2Es(CourseDoc doc) {
        esCourseRepository.save(doc);
        Iterable<CourseDoc> all = esCourseRepository.findAll();
        for (CourseDoc courseDoc : all) {
            System.out.println(courseDoc.getName());
        }
        System.out.println("--------"+all);
    }
    @Override
    public void deleteCourseInEs(Long courseId) {
        esCourseRepository.deleteById(courseId);
    }

    /**
     * 从Es搜索课程相关的
     * @param dto
     * @return
     */
    @Override
    public PageList<CourseDoc> searchCourseDoc(SearchCourseDto dto) {
        //1.创建NativeSearchQuery的创建者
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //2.给builder配置一些查询的条件
        if(StringUtils.hasLength(dto.getSortField())){
            // dto.getSortField()  xl rq  xp pl
            String sortField = null;
            switch (dto.getSortField().toLowerCase()){
                case "xl": sortField="saleCount";break;
                case "xp": sortField="onlineTime";break;
                case "pl": sortField="commentCount";break;
                case "jg": sortField="price";break;
                case "rq": sortField="viewCount";break;
                default: break;
            }
            if(sortField != null){
                if(StringUtils.hasLength(dto.getSortType())){
                    SortOrder sortOrder = dto.getSortType().equalsIgnoreCase("ASC") ? SortOrder.ASC : SortOrder.DESC;
                    builder.withSort(new FieldSortBuilder(sortField).order(sortOrder));
                }
            }
        }
        //封装分页相关的参数===================  0 代表第一页
        builder.withPageable(PageRequest.of(dto.getPage()-1, dto.getRows()));
        //PageRequest pageRequest = PageRequest.of(dto.getPage()-1, dto.getRows());
        //封装查询条件========================
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //DSL查询  private String keyword;//关键字-------
        if(StringUtils.hasLength(dto.getKeyword())){
            boolQuery.must(QueryBuilders.matchQuery("name",dto.getKeyword()));
        }
        //DSL过滤-----------------
        if(dto.getCourseTypeId() != null){
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId",dto.getCourseTypeId()));
        }
        if(StringUtils.hasLength(dto.getGradeName())){
            boolQuery.filter(QueryBuilders.termQuery("gradeName",dto.getGradeName()));
        }
        if(StringUtils.hasLength(dto.getChargeName())){
            boolQuery.filter(QueryBuilders.termQuery("chargeName",dto.getChargeName()));
        }
        if(dto.getPriceMin() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(dto.getPriceMin()));
        }
        if(dto.getPriceMax() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").lte(dto.getPriceMax()));
        }

        builder.withQuery(boolQuery);
        //6.做关键字高亮的条件
        builder.withHighlightFields(new HighlightBuilder.Field("name")
                .preTags("<font style='color:red'>")
                .postTags("</font>"));

        //8.做聚合的条件,terms 分组统计，terms统计后的 别名组。field对es中的哪一个字段做统计。
        builder.addAggregation(AggregationBuilders.terms("aggsGradeName").field("gradeName"));
        builder.addAggregation(AggregationBuilders.terms("aggsChargeName").field("chargeName"));




        //3.根据条件配置，创建出实例的条件对象
        NativeSearchQuery nativeSearchQuery = builder.build();
        //4.根据条件对象去搜索出结果
        //Page<CourseDoc> page = esCourseRepository.search(nativeSearchQuery);
        //7.AggregatedPage是其Page的子类  这个设置了高亮
        AggregatedPage<CourseDoc> page = elasticsearchRestTemplate.queryForPage(nativeSearchQuery, CourseDoc.class, highlightResultMapper);

        //8.1 处理聚合的数据
        Map<String, Aggregation> aggregationMap = page.getAggregations().asMap();//是等级 和 收费的捅的集合，根据别名转为map
        //获取每一个等级捅的集合
        ParsedTerms aggsGradeNameResult = (ParsedTerms)aggregationMap.get("aggsGradeName");
        //获取每一个等级捅的集合
        ParsedTerms aggsChargeNameResult = (ParsedTerms)aggregationMap.get("aggsChargeName");

        //8.2处理捅集合的数据
        ArrayList<AggrsBucket> aggrsGradeBuckets = new ArrayList<>();
        aggsGradeNameResult.getBuckets().forEach(bucket -> {
            String key=bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            aggrsGradeBuckets.add(new AggrsBucket(key,docCount));
        });
        //处理收费的数据
        ArrayList<AggrsBucket> aggrsChargeBuckets = new ArrayList<>();
        aggsChargeNameResult.getBuckets().forEach(bucket -> {
            String key=bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            aggrsChargeBuckets.add(new AggrsBucket(key,docCount));
        });
        HashMap<String, List<AggrsBucket>> map = new HashMap<>();
        map.put("aggsGradeName",aggrsGradeBuckets);
        map.put("aggsChargeName",aggrsChargeBuckets);

        //5.封装结果集
        /*PageList<CourseDoc> pageList = new PageList<>();
        pageList.setTotal(page.getTotalElements());
        pageList.setRows(page.getContent());*/
        return new EsAggsPageList<>(page.getTotalElements(),page.getContent(),map);
    }
}
